package main

import (
  "net"
  "fmt"
  "flag"
  "os"
  "io"
)

type Client struct {
  ServerIp string
  ServerPort int
  Name string
  conn net.Conn
  flag int
}

func(this *Client)menu() bool{
  var flag int
  fmt.Println("1.public chat")
  fmt.Println("2.private chat")
  fmt.Println("3.rename")
  fmt.Println("0.exit")
  fmt.Scanln(&flag)
  if flag >=0 && flag <= 3 {
    this.flag = flag
    return true
  }else{
    return false
  }

}

func (this *Client) Rename() bool{
  fmt.Printf("please input username:")
  fmt.Scanln(&this.Name)

  msg := "rename|"+this.Name+"\n"
  _,err := this.conn.Write([]byte(msg))
  if err != nil {
    fmt.Println("conn.write error:",err)
    return false
  }
  return true
}

func (this *Client) PublicChat() {
  var chatMsg string

  fmt.Println(">>>>please input message, 0 for exit.")
  fmt.Scanln(&chatMsg)

  for chatMsg != "0" {
    if len(chatMsg) > 0 {
      sendMsg := chatMsg + "\n"
      _, err := this.conn.Write([]byte(sendMsg))
      if err != nil {
        fmt.Println("conn write err:",err)
        break
      }


      chatMsg = ""
      //read one line
      fmt.Println(">>>>please input message, 0 for exit.")
      fmt.Scanln(&chatMsg)
    }
  }

}

func (this *Client) ShowUsers(){
  sendMsg := "who\n"
  _,err := this.conn.Write([]byte(sendMsg))
  if err != nil {
    fmt.Println("conn.write err:",err)
    return
  }
}

func(this *Client) PrivateChat(){
  var rName string
  var chatMsg string

  this.ShowUsers()
  fmt.Println(">>>>select user to chat. 0 for exit.")
  fmt.Scanln(&rName)

  for rName != "0" {
    chatMsg = ""
    //read one line
    fmt.Println(">>>>please input message, 0 for exit.")
    fmt.Scanln(&chatMsg)

    for chatMsg != "0" {
      if len(chatMsg) > 0 {
        sendMsg := "to|"+rName+"|"+chatMsg + "\n\n"
        _, err := this.conn.Write([]byte(sendMsg))
        if err != nil {
          fmt.Println("conn write err:",err)
          break
        }
      }

      chatMsg = ""
      //read one line
      fmt.Println(">>>>please input message, 0 for exit.")
      fmt.Scanln(&chatMsg)
    }

    this.ShowUsers()
    fmt.Println(">>>>select user to chat. 0 for exit.")
    fmt.Scanln(&rName)

  }



}

func(this *Client) ShowResponse(){
  io.Copy(os.Stdout, this.conn)
  // same as below
  // for {
  //   //buf := make([]byte string,1024)
  //   buf := make()
  //   client.conn.Read(buf)
  //   fmt.Println(buf)
  // }
}

func(this *Client) Run(){
  for this.flag != 0 {
    for !this.menu(){}

    switch this.flag {
    case 1: 
      this.PublicChat()
      break
    case 2: 
      this.PrivateChat()
      break
    case 3: 
      this.Rename()
      break
    case 0: break
  }
  }
}

func NewClient(ip string, port int) *Client {
  client := &Client{
    ServerIp: ip,
    ServerPort: port,
    flag: 999,
  }

  conn, err := net.Dial("tcp", fmt.Sprintf("%s:%d", ip, port))
  if err != nil {
    fmt.Println("net.Dial Error: ", err)
    return nil
  }

  client.conn = conn

  return client
}

var serverIp string
var serverPort int
// ./client -ip 127.0.0.1
func init(){
  flag.StringVar(&serverIp, "ip", "localhost", "on default, server run on localhost")
  flag.IntVar(&serverPort, "port", 8888, "default port 8888")
}

func main(){
  flag.Parse()

  client := NewClient(serverIp, serverPort)
  if client != nil {
    fmt.Println("connection established.")
  }else {
    fmt.Println("connection failed.")
  }

  go client.ShowResponse()
  client.Run()

}
